package com.kaili.zuul.security;

import com.alibaba.fastjson.JSONObject;
import com.kaili.common.response.CommonStatus;
import com.kaili.common.response.ResponseData;
import com.kaili.zuul.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.session.InvalidSessionStrategy;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;


@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public SessionRegistry getSessionRegistry(){
        SessionRegistry sessionRegistry=new SessionRegistryImpl();
        return sessionRegistry;
    }

    @Autowired
    LoginService baseUserService;
    @Autowired
    FailureHandler failureHandler;
    @Autowired
    SuccessHandler successHandler;

    @Autowired
    AuthenticationDetailsSource<HttpServletRequest,WebAuthenticationDetails> cg;

    @Autowired
    AuthenticationProvider ca;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        auth.userDetailsService(baseUserService).passwordEncoder(new BCryptPasswordEncoder());
        auth.authenticationProvider(ca);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
      web.ignoring().antMatchers("/kaili-basic/v1/pdas/veriBySn", "/v2/api-docs", "/configuration/ui", "/swagger-resources*//**//**",
              "/configuration/security", "/webjars*//**//**", "/base/config/login_p", "/kaili-basic/v1/companys/verifyCode", "/kaili-basic/v1/companys/register",
              "/kaili-basic/v1/getCode", "/kaili-basic/v1/getDH", "/kaili-basic/v1/companys/url");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
//        http.addFilter(calendar());
//        http.authenticationProvider(ca);
        http.authorizeRequests().anyRequest().fullyAuthenticated();
        http.formLogin().permitAll().usernameParameter("username").passwordParameter("username_P").authenticationDetailsSource(cg).failureHandler(failureHandler).successHandler(successHandler);
        http.headers().frameOptions().disable();
        http.csrf().disable();
        http.logout().logoutSuccessHandler(new LogoutSuccessHandler() {
            @Override
            public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                response.setContentType("application/json;charset=utf-8");
                PrintWriter out = response.getWriter();
                String s = JSONObject.toJSONString(new ResponseData("退出成功", CommonStatus.OK));
                out.write(s);
                out.flush();
                out.close();
            }
        });
        http.exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPoint() {
            @Override
            public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
                response.setContentType("application/json;charset=utf-8");
                PrintWriter out = response.getWriter();
                String s = JSONObject.toJSONString(new ResponseData(CommonStatus.FORBIDDEN));
                out.write(s);
                out.flush();
                out.close();
            }
        });
        http.exceptionHandling().accessDeniedHandler(new AccessDeniedHandler() {
            @Override
            public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
                response.setContentType("application/json;charset=utf-8");
                PrintWriter out = response.getWriter();
                String s = JSONObject.toJSONString(new ResponseData("权限不足",CommonStatus.FORBIDDEN));
                out.write(s);
                out.flush();
                out.close();
            }
        });
        http.sessionManagement().invalidSessionStrategy(new InvalidSessionStrategy() {
            @Override
            public void onInvalidSessionDetected(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException, ServletException {
                httpServletResponse.setContentType("application/json;charset=utf-8");
                PrintWriter out = httpServletResponse.getWriter();
                String s = JSONObject.toJSONString(new ResponseData("身份失效",CommonStatus.FORBIDDEN));
                out.write(s);
                out.flush();
                out.close();
            }
        });
        String paramValue = baseUserService.getParamValue("Principals");
        if (paramValue!=null && paramValue.equals("1")){
            http.sessionManagement().maximumSessions(1).sessionRegistry(getSessionRegistry()).expiredUrl("/login");
        }

    }

}
